package com.wangsan.study.web.security;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.google.common.collect.Lists;
import com.wangsan.study.domain.ResourceEntity;
import com.wangsan.study.security.ResourceAuthItem;
import com.wangsan.study.service.ResourceEntityService;

/**
 * DbResourceAuthMerger
 *
 * @author wangsan
 * @date 2016/12/30
 */
@Component
public class DbResourceAuthMerger implements InitializingBean {
    private static final Logger LOGGER = LoggerFactory.getLogger(DbResourceAuthMerger.class);

    @Autowired
    private ResourceEntityService resourceEntityService;
    @Autowired
    private AnnotationResourceAuthResolver annotationResourceAuthResolver;
    private Boolean dbUpdate = false;

    public void merge(List<ResourceAuthItem> resourceAuthItemList) {
        Map<String, ResourceAuthItem> itemMap = resourceAuthItemList.stream()
                .collect(Collectors.toMap(
                        ResourceAuthItem::getPath,
                        Function.identity(),
                        (u, v) -> v, // 保留后者
                        LinkedHashMap::new
                ));

        List<ResourceEntity> entityList = Lists.newArrayList(resourceEntityService.findAll());
        Map<String, ResourceEntity> entityMap =
                entityList.stream().collect(Collectors.toMap(ResourceEntity::getPath, Function.identity()));

        // 数据库优先，主动添加数据库中没有的path
        List<ResourceAuthItem> addList = new ArrayList<>();
        List<ResourceAuthItem> updateList = new ArrayList<>();
        itemMap.forEach((path, item) -> {
            if (!entityMap.containsKey(path)) {
                addList.add(item);
            } else {
                updateList.add(item);
            }
        });

        List<ResourceEntity> addEntityList = addList.stream().map(item -> {
            LOGGER.info("save resourceAuth to db:{}", item);
            ResourceEntity entity = new ResourceEntity();
            entity.setAuthGroup(item.getGroup());
            entity.setAuthName(item.getName());
            entity.setPath(item.getPath());
            return entity;
        }).collect(Collectors.toList());

        // do add
        resourceEntityService.save(addEntityList);

        // do update
        if (dbUpdate) {
            updateList.forEach(item -> updateByItem(item));
        }
    }

    private ResourceEntity updateByItem(ResourceAuthItem authItem) {
        LOGGER.info("update resourceAuth to db:{}", authItem);
        ResourceEntity entity = resourceEntityService.findByPath(authItem.getPath());
        entity.setAuthGroup(authItem.getGroup());
        entity.setAuthName(authItem.getName());
        return resourceEntityService.save(entity);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        List<ResourceAuthItem> itemList = annotationResourceAuthResolver.getResourceAuthItemList();
        merge(itemList);
    }
}
